/*
REWRITTEN FROM SCRATCH BY XINEF, IT OWNS NOW!
*/

#include "ScriptMgr.h"
#include "ScriptedCreature.h"
#include "utgarde_pinnacle.h"

class instance_pinnacle : public InstanceMapScript
{
public:
    instance_pinnacle() : InstanceMapScript("instance_pinnacle", 575) { }

    InstanceScript* GetInstanceScript(InstanceMap* pMap) const
    {
        return new instance_pinnacle_InstanceMapScript(pMap);
    }

	struct instance_pinnacle_InstanceMapScript : public InstanceScript
	{
		instance_pinnacle_InstanceMapScript(Map* pMap) : InstanceScript(pMap) {Initialize();};

		uint64 SvalaSorrowgrave;
		uint64 GortokPalehoof;
		uint64 SkadiRuthless;
		uint64 KingYmiron;
		uint64 FrenziedWorgen;
		uint64 RavenousFurbolg;
		uint64 MassiveJormungar;
		uint64 FerociousRhino;
		uint64 Grauf;

		uint64 SvalaMirrorGUID;
		uint64 SkadiRuthlessDoor;
		uint64 YmironDoor;
		uint64 StatisGenerator;
		uint32 FightStatus;
		uint32 Encounters[MAX_ENCOUNTERS];
		uint8 SkadiHits;
		uint8 SkadiInRange;

		bool svalaAchievement;
		bool skadiAchievement;
		bool ymironAchievement;

		void Initialize()
		{
		   SvalaSorrowgrave	= 0;
		   GortokPalehoof	= 0;
		   SkadiRuthless	= 0;
		   KingYmiron		= 0;
   		   FrenziedWorgen	= 0;
   		   RavenousFurbolg	= 0;
   		   MassiveJormungar	= 0;
   		   FerociousRhino	= 0;
		   Grauf			= 0;

		   SvalaMirrorGUID	= 0;
		   StatisGenerator	= 0;
		   SkadiHits		= 0;
		   SkadiInRange		= 0;
   		   SkadiRuthlessDoor= 0;
   		   YmironDoor		= 0;
		   FightStatus		= 0;

		   svalaAchievement = false;
		   skadiAchievement = false;
		   ymironAchievement = false;
		   
		   for(uint8 i = 0; i < MAX_ENCOUNTERS; ++i)
			   Encounters[i] = NOT_STARTED;
		}

		bool IsEncounterInProgress() const
		{
			for(uint8 i = 0; i < MAX_ENCOUNTERS; ++i)
				if(Encounters[i] == IN_PROGRESS) 
					return true;

			return false;
		}
		void OnCreatureCreate(Creature* pCreature)
		{
			switch(pCreature->GetEntry())
			{
				case NPC_SVALA_SORROWGRAVE: SvalaSorrowgrave = pCreature->GetGUID();         break;
				case NPC_GORTOK_PALEHOOF: GortokPalehoof = pCreature->GetGUID();           break;
				case NPC_SKADI_THE_RUTHLESS: SkadiRuthless = pCreature->GetGUID();            break;
				case NPC_KING_YMIRON: KingYmiron = pCreature->GetGUID();               break;
				case NPC_FRENZIED_WORGEN: FrenziedWorgen = pCreature->GetGUID();           break;
				case NPC_RAVENOUS_FURBOLG: RavenousFurbolg = pCreature->GetGUID();          break;
				case NPC_MASSIVE_JORMUNGAR: MassiveJormungar = pCreature->GetGUID();         break;
				case NPC_FEROCIOUS_RHINO: FerociousRhino = pCreature->GetGUID();           break;
				case NPC_GARUF: Grauf = pCreature->GetGUID();                    break;
			}
		}

		void OnGameObjectCreate(GameObject* pGo)
		{
			switch(pGo->GetEntry())
			{
				case GO_SKADI_THE_RUTHLESS_DOOR:
					SkadiRuthlessDoor = pGo->GetGUID();
					if (Encounters[DATA_SKADI_THE_RUTHLESS] == DONE)
						HandleGameObject(0,true,pGo);
					break;
				case GO_KING_YMIRON_DOOR:
					YmironDoor = pGo->GetGUID();
					if (Encounters[DATA_KING_YMIRON] == DONE) 
						HandleGameObject(0,true,pGo);
					break;
				case GO_GORK_PALEHOOF_SPHERE: 
					StatisGenerator = pGo->GetGUID();
					break;
				case GO_SVALA_MIRROR:
					SvalaMirrorGUID = pGo->GetGUID();
					break;
			}
		}

		bool CheckAchievementCriteriaMeet(uint32 criteria_id, Player const* source, Unit const* target = NULL, uint32 miscvalue1 = 0)
		{
			switch(criteria_id)
			{
				case 7322: // The Incredible Hulk (2043)
					return svalaAchievement;
				case 7595: // My Girl Loves to Skadi All the Time (2156)
					return skadiAchievement;
				case 7598: // King's Bane (2157)
					return ymironAchievement;
			}
			return false;
		}

		void SetData(uint32 type, uint32 data)
		{
			switch(type)
			{
				case DATA_SVALA_SORROWGRAVE:
				case DATA_GORTOK_PALEHOOF:
					Encounters[type] = data;
					break;
				case DATA_SKADI_THE_RUTHLESS:
					if (data == DONE)
					{
						HandleGameObject(SkadiRuthlessDoor,true);
						// Make ymiron attackable
						if (Creature *cr = instance->GetCreature(KingYmiron))
							cr->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE);
					}
					Encounters[type] = data;
					break;
				case DATA_KING_YMIRON:
					if (data == DONE)
						HandleGameObject(YmironDoor,true);
					Encounters[type] = data;
					break;
				case SKADI_HITS:
					SkadiHits = data;
					break;
				case SKADI_IN_RANGE:
					SkadiInRange = data;
					break;
				case DATA_SVALA_ACHIEVEMENT:
					svalaAchievement = (bool)data;
					return;
				case DATA_SKADI_ACHIEVEMENT:
					skadiAchievement = (bool)data;
					return;
				case DATA_YMIRON_ACHIEVEMENT:
					ymironAchievement = (bool)data;
					return;

			}
			OUT_SAVE_INST_DATA;

			SaveToDB();
			OUT_SAVE_INST_DATA_COMPLETE;
		}

		std::string GetSaveData()
		{
			std::ostringstream saveStream;
			saveStream << "U P " << Encounters[0] << ' ' << Encounters[1] << ' ' << Encounters[2] << ' ' << Encounters[3];
			return saveStream.str();
		}

		void Load(const char* in)
		{
			if (!in)
			{
				OUT_LOAD_INST_DATA_FAIL;
				return;
			}

			OUT_LOAD_INST_DATA(in);

			char dataHead1, dataHead2;
			uint16 data0, data1, data2, data3;

			std::istringstream loadStream(in);
			loadStream >> dataHead1 >> dataHead2 >> data0 >> data1 >> data2 >> data3;

			if (dataHead1 == 'U' && dataHead2 == 'P')
			{
				Encounters[0] = data0;
				Encounters[1] = data1;
				Encounters[2] = data2;
				Encounters[3] = data3;

				for (uint8 i = 0; i < MAX_ENCOUNTERS; ++i)
					if (Encounters[i] == IN_PROGRESS)
						Encounters[i] = NOT_STARTED;

			} else OUT_LOAD_INST_DATA_FAIL;

			OUT_LOAD_INST_DATA_COMPLETE;
		}

		uint32 GetData(uint32 type) const
		{
			switch(type)
			{
				case DATA_SVALA_SORROWGRAVE:        return Encounters[0];
				case DATA_GORTOK_PALEHOOF:          return Encounters[1];
				case DATA_SKADI_THE_RUTHLESS:       return Encounters[2];
				case DATA_KING_YMIRON:              return Encounters[3];
				case SKADI_HITS:					return SkadiHits;
				case SKADI_IN_RANGE:			    return SkadiInRange;
			}
			return 0;
		}

		uint64 GetData64(uint32 identifier) const
		{
			switch(identifier)
			{
				case DATA_SVALA_SORROWGRAVE:          return SvalaSorrowgrave;
				case DATA_GORTOK_PALEHOOF:            return GortokPalehoof;
				case DATA_SKADI_THE_RUTHLESS:         return SkadiRuthless;
				case DATA_KING_YMIRON:                return KingYmiron;
				case DATA_NPC_FRENZIED_WORGEN:        return FrenziedWorgen;
				case DATA_NPC_RAVENOUS_FURBOLG:       return RavenousFurbolg;
				case DATA_NPC_MASSIVE_JORMUNGAR:      return MassiveJormungar;
				case DATA_NPC_FEROCIOUS_RHINO:        return FerociousRhino;
				case YMIRON_DOOR:					  return YmironDoor;
				case STATIS_GENERATOR:				  return StatisGenerator;
				case SKADI_DOOR:					  return SkadiRuthlessDoor;
				case DATA_GRAUF:					  return Grauf;
				case GO_SVALA_MIRROR:				  return SvalaMirrorGUID;
			}

			return 0;
		}
	};
};

void AddSC_instance_utgarde_pinnacle()
{
    new instance_pinnacle();
}